package sql

import (
	"fmt"
	"reflect"
	"strings"

	"vitess.io/vitess/go/sqltypes"
)

// Row is a tuple of values.
type Row struct {
	schema   Schema
	values   []interface{}
	capacity int
	position int
}

func (r *Row) Append(vals ...interface{}) *Row {
	if vals != nil {
		for i, v := range vals {
			if r.position < r.capacity {
				r.values[r.position+i] = v
			}
		}
		r.position = r.position + len(vals)
	}
	return r
}

// Copy creates a new Row with the same values as the current one.
func (r *Row) Copy() *Row {
	row := &Row{
		schema:   r.schema,
		values:   make([]interface{}, r.capacity),
		capacity: r.capacity,
		position: 0,
	}
	for i, v := range r.values {
		row.values[i] = v
	}
	return row
}

func (r *Row) ToSQL() []sqltypes.Value {
	row := make([]sqltypes.Value, r.capacity)
	for i, v := range r.values {
		if v == nil {
			row[i] = sqltypes.NULL
			continue
		}
		col := r.schema.GetColumn(i)
		//缺少类型转换，需要给column中添加转换
		row[i] = sqltypes.MakeTrusted(col.Type, col.ToBytes(v))
	}
	return row
}

func (r *Row) Check() error {
	for idx, f := range r.schema {
		v := r.values[idx]
		if f.Check(v) {
			continue
		}
		typ := reflect.TypeOf(v).String()
		return ErrUnexpectedType.New(idx, typ)
	}
	return nil
}

func (r *Row) Format() string {
	return FormatRow(r)
}

// FormatRow returns a formatted string representing this Row's values
func FormatRow(row *Row) string {
	var sb strings.Builder
	sb.WriteRune('[')
	for i, v := range row.values {
		if i > 0 {
			sb.WriteRune(',')
		}
		sb.WriteString(fmt.Sprintf("%v", v))
	}
	sb.WriteRune(']')
	return sb.String()
}
